Skip to content

v0.6.0: robust feed parsing, CN host coverage, Podcast Index support#4

Merged
xiaoleiy merged 25 commits into
mainfrom
feed-robustness-podcastindex
Jul 8, 2026
Merged

v0.6.0: robust feed parsing, CN host coverage, Podcast Index support#4
xiaoleiy merged 25 commits into
mainfrom
feed-robustness-podcastindex

Conversation

@xiaoleiy

@xiaoleiy xiaoleiy commented Jul 8, 2026

Copy link
Copy Markdown
Owner

v0.6.0 — robust feed parsing, Chinese-market host coverage, Podcast Index support

Implements the approved design spec (docs/superpowers/specs/2026-07-07-feed-robustness-podcastindex-design.md); built task-by-task from the committed plan with two-stage review per task.

Feed parsing robustness (core.py, still pure stdlib)

  • Namespace-agnostic parsing by localname: RSS 2.0, RSS 1.0 (RDF), and Atom all supported; bare tags beat namespaced synonyms (<title> wins over <itunes:title> regardless of document order).
  • Enclosure discovery with fallbacks: <enclosure> → audio media:content → Atom link rel="enclosure"; duplicate enclosure+media:content items (WavPub/Omny) yield exactly one episode.
  • Dirty-XML sanitize-and-retry: undefined HTML entities, bare &, control chars, junk before the declaration, real UTF-16 detection (BOM + BOM-less) — CDATA-safe, unknown entities preserved, and still fails loudly on hopeless input.
  • ISO-8601 pub dates (Atom/dc:date), incl. colon-less offsets normalized for py3.9.
  • ximalaya.com/album/<id> links accepted directly (Ximalaya Podcast托管 RSS).
  • Download guard: text/* responses (e.g. Ximalaya CDN's 200-with-7-byte-body stale-enclosure trap) now raise instead of writing garbage audio.

Podcast Index (optional, BYOK)

  • Set PODCASTINDEX_API_KEY/PODCASTINDEX_API_SECRET (free) to enrich search (merged + deduped with iTunes, graceful per-backend degradation) and gain a feed-resolution fallback when the iTunes lookup has no feed.
  • Without keys: behavior byte-identical, and a regression test hard-fails if PI ever touches the network credential-less.

Tests

  • 20 offline feed fixtures pinning real host quirks: 忽左忽右/xiaoyuzhou, 声动早咖啡/Ximalaya, 股癌/SoundOn, 百靈果/Firstory, 半拿铁/WavPub, 疯投圈/Typlog, 科技早知道/Fireside, 大内密谈/Lizhi + Anchor/Acast/Omny/Libsyn/Transistor + synthetic edge cases (Atom, RDF, dirty entities, UTF-16, MRSS-only).
  • Browser-UA invariant pinned (SoundOn/Typlog/Fireside/Lizhi CDN 403 Python-urllib).
  • pytest -m network live suite (excluded by default): all 5 pass against the real hosts.
  • Suite: 22 → 60 offline tests, all green; ruff clean.

Docs

  • README: Podcast Index section, ximalaya input, refreshed roadmap. CHANGELOG 0.6.0 (incl. Add a --quiet flag to podpull get #3's --quiet). Integrations (SKILL.md/OpenCode/Cursor) updated. Version bumped in both __init__.py and pyproject.toml.

Rebased on main after #3 (--quiet) merged; no dependency changes (no Homebrew resource work needed).

🤖 Generated with Claude Code

xiaoleiy and others added 25 commits July 8, 2026 14:43
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… classify, download guard

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…bug)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tities

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… transistor

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nt 5)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tion)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…note

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@xiaoleiy xiaoleiy merged commit 6509ec5 into main Jul 8, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant